package com.heima.lock;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class StockController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private WmLockMapper lockMapper;

    @GetMapping("/stock")
    public String stock() {
        synchronized ("abc") {
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }
        }
        return "OK";
    }

    /**
     * 分布式锁：基于mysql实现
     *
     * @return
     */
    @GetMapping("/stock1")
    public String stock1() {
        //1. 获取分布式锁：谁能往表中成功的插入数据，那么就表示谁抢到了锁
        WmLock lock = WmLock.builder().mylock("DBlock").threadId(Thread.currentThread().getId()).build();
        try {
            lockMapper.insert(lock);
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }
        } catch (Exception e) {
            System.out.println("没有抢到分布式锁");
        } finally {
            WmLock wmLock = lockMapper.selectOne(Wrappers.<WmLock>lambdaQuery().eq(WmLock::getThreadId, Thread.currentThread().getId()));
            if (wmLock != null) {
                //释放锁
                lockMapper.deleteById(lock.getId());
            }
        }

        return "OK";
    }


    /**
     * 分布式锁：基于redis实现
     *
     * @return
     */
    @GetMapping("/stock2")
    public String stock2() {
        //1. 获取分布式锁：谁能往redis中成功的插入数据，那么就表示谁抢到了锁
        Boolean isLock = redisTemplate.opsForValue().setIfAbsent("lock", String.valueOf(Thread.currentThread().getId()), 30, TimeUnit.SECONDS);
        try {
            if (isLock) {
                Integer stock = Integer.valueOf(redisTemplate.opsForValue().get("stock"));
                if (stock != null) {
                    stock--;
                    if (stock >= 0) {
                        redisTemplate.opsForValue().set("stock", String.valueOf(stock));
                        System.out.println("库存还剩" + stock + "个");
                    } else {
                        System.out.println("库存不足");
                    }
                } else {
                    System.out.println("未查询到该商品库存");
                }
            } else {
                System.out.println("未抢到锁");
            }
        } catch (Exception e) {
            System.out.println("业务处理异常");
        } finally {
            String lock = redisTemplate.opsForValue().get("lock");
            if (StringUtils.isNotEmpty(lock) && lock.equals(String.valueOf(Thread.currentThread().getId()))) {
                redisTemplate.delete("lock");
            }
        }
        return "ok";
    }

    @Autowired
    private RedissonClient redisson;

    /**
     * 分布式锁：基于reddsion实现
     *
     * @return
     */
    @GetMapping("/stock3")
    public String stock3() {
        //1. 获取锁对象
        RLock lock = redisson.getLock("lock");
        lock.lock();
        try {
            Integer stock = Integer.valueOf(redisTemplate.opsForValue().get("stock"));
            if (stock != null) {
                stock--;
                if (stock >= 0) {
                    redisTemplate.opsForValue().set("stock", String.valueOf(stock));
                    System.out.println("库存还剩" + stock + "个");
                } else {
                    System.out.println("库存不足");
                }
            } else {
                System.out.println("未查询到该商品库存");
            }
        } catch (NumberFormatException e) {
            System.out.println("业务处理异常");
        } finally {
            lock.unlock();
        }
        return "ok";
    }
}